﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace RdH.XMLToolbox.InsertDTD
{
    public class DTDInserter
    {
        private String xmlHeader = "";
        private String dtdReference = "";
        private String startingTag = "";
        private String source;
        private String destination;
        public bool RecurseFolder { get; set; }
        public bool PreserveXmlHeader { get; set; }

        public String Source 
        {
            get
            {
                return source;
            }
            set
            {
                if (File.Exists(value) || Directory.Exists(value))
                    source = value;
                else
                    throw new ArgumentException("The Source argument is invalid.");
            }
        }
        public String Destination 
        {
            get
            {
                return destination;
            }

            set
            {
                if (File.Exists(value) || Directory.Exists(value))
                    destination = value;
                else if (Directory.Exists(Path.GetDirectoryName(value)))
                    destination = value;
                else
                    throw new ArgumentException("The Destination argument is invalid.");
            }
        }

        public DTDInserter(String source, String destination)
        {
            this.Source = source;
            this.Destination = destination;
        }

        private void Process()
        {
            if (Directory.Exists(source))
            {
                SearchOption option = (RecurseFolder == true) ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;

                foreach (String file in Directory.GetFiles(Source, "*.sgml;*.xml", option))
                {
                    ProcessFile(file);
                }
            }
            else
            {
                ProcessFile(Source);
            }
        }

        private void ProcessFile(String file)
        {
            StreamReader sr = new StreamReader(file);
            String data = sr.ReadToEnd();
            sr.Close();

            if (data.Length > 0)
            {
                if (PreserveXmlHeader)
                {
                    Match headerMatch = Regex.Match(data, @"<\?.+\?>");
                    if (headerMatch.Success) xmlHeader = headerMatch.Value;
                }

                int rootNodePosition = data.IndexOf("<" + startingTag);
                if (rootNodePosition > 0)
                {
                    string rootNode = data.Substring(rootNodePosition);

                    if (rootNode.Length > 0)
                    {
                        string result = xmlHeader + "\r\n" + dtdReference + "\r\n" + rootNode;
                        string outputFile = destination;
                        
                        if (!Directory.Exists(outputFile))
                            outputFile = Path.Combine(outputFile, Path.GetFileName(source));

                        StreamWriter sw = new StreamWriter(outputFile);
                        sw.Write(result);
                        sw.Close();
                    }
                }
            }
        }

        public void Process(String dtdReference, String startingTag)
        {
            this.dtdReference = dtdReference;
            this.startingTag = startingTag;
            Process();
        }

        public void Process(String dtdReference, String startingTag, String xmlHeader)
        {
            this.xmlHeader = xmlHeader;
            PreserveXmlHeader = false;

            Process(dtdReference, startingTag);
        }
    }
}
